package com.swak.redis.aspect;

import java.lang.reflect.Method;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;

import com.swak.Constants;
import com.swak.annotation.cache.DeleteCache;
import com.swak.asm.FieldCache;
import com.swak.asm.FieldCache.ClassMeta;
import com.swak.asm.FieldCache.FieldMeta;
import com.swak.redis.RedisLocalCache;
import com.swak.redis.RedisService;
import com.swak.utils.StringUtils;

/**
 * 定义： 切面
 * 
 * @author DELL
 */
@Aspect
public class DeleteCacheAspect implements Ordered {

	@Autowired
	private RedisService redisService;
	@Autowired
	private RedisLocalCache localCache;

	/**
	 * 拦截刪除緩存
	 */
	@Pointcut("@annotation(com.swak.annotation.cache.DeleteCache)")
	public void DeleteCache_Pointcut_Interceptor() {
	}

	/**
	 * 拦截器处理方法
	 * 
	 * @param point
	 * @return
	 * @throws Throwable
	 */
	@Around("DeleteCache_Pointcut_Interceptor()")
	public Object around(ProceedingJoinPoint point) throws Throwable {
		Object result = point.proceed();
		Method method = ((MethodSignature) point.getSignature()).getMethod();
		DeleteCache deleteCache = method.getAnnotation(DeleteCache.class);
		if (result != null && deleteCache != null) {
			ClassMeta classMeta = FieldCache.checkAndSet(result.getClass());
			FieldMeta fieldMeta = classMeta.getField(deleteCache.field());
			Object value = fieldMeta != null ? fieldMeta.getFieldValue(result) : null;
			if (StringUtils.isNotBlank(deleteCache.hashKey()) && !deleteCache.hashDelAll()) {
				this.deleteHashCache(deleteCache, value);
			} else if (StringUtils.isNotBlank(deleteCache.hashKey())) {
				this.deleteHashCache(deleteCache);
			} else {
				this.deleteCache(deleteCache, value);
			}
		}
		return result;
	}

	private void deleteCache(DeleteCache deleteCache, Object value) {
		String keyName = new StringBuilder(deleteCache.name().toUpperCase()).append(Constants.Cache_Separate_Key)
				.append(String.valueOf(value)).toString();
		this.redisService.sync().del(keyName);
		this.localCache.sendEvictCmdAndDeleteLocal(keyName);
	}

	private void deleteHashCache(DeleteCache deleteCache, Object value) {
		String keyName = new StringBuilder(deleteCache.name().toUpperCase()).append(Constants.Cache_Separate_Key)
				.append(deleteCache.hashKey()).toString();
		this.redisService.sync().hDel(keyName, String.valueOf(value));
		this.localCache.sendEvictCmdAndDeleteLocal(keyName);
	}

	private void deleteHashCache(DeleteCache deleteCache) {
		String keyName = new StringBuilder(deleteCache.name().toUpperCase()).append(Constants.Cache_Separate_Key)
				.append(deleteCache.hashKey()).toString();
		this.redisService.sync().del(keyName);
		this.localCache.sendEvictCmdAndDeleteLocal(keyName);
	}

	/**
	 * Aop的顺序要早于spring的事务
	 * 注意Order序号要小于{@link org.springframework.aop.interceptor.ExposeInvocationInterceptor},
	 * PriorityOrdered.HIGHEST_PRECEDENCE + 1
	 */
	@Override
	public int getOrder() {
		return Ordered.HIGHEST_PRECEDENCE;
	}

}
